package fr.doume.jna.authenticator;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;


import org.apache.catalina.Context;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.RequestFacade;


import org.apache.catalina.Authenticator;
import org.apache.catalina.Pipeline;
import org.apache.catalina.Valve;
import fr.doume.jna.authenticator.SSPAuthenticator;

import org.apache.catalina.core.ApplicationContextFacade;
import org.apache.catalina.core.ApplicationContext;
import java.lang.reflect.Field;

import java.lang.NoSuchFieldException;
import java.lang.IllegalAccessException;
import java.lang.SecurityException;



  public class LoginAuthenticator
  {
    private static SSPAuthenticator getSSPAuthenticator(ServletContext ctx)
    throws ServletException
    {
        //ServletContext ctx = servlet.getServletContext();
        ApplicationContext appctx = getContext_ac(ctx);
        StandardContext stdctx = getContext(appctx);
        
        Pipeline pipeline = stdctx.getPipeline();
        if (pipeline != null) {
            Valve basic = pipeline.getBasic();
            if ((basic != null) && (basic instanceof SSPAuthenticator))
                return (SSPAuthenticator) basic;
            Valve valves[] = pipeline.getValves();
            for (int i = 0; i < valves.length; i++) {
                if (valves[i] instanceof SSPAuthenticator)
                    return (SSPAuthenticator) valves[i];
            }
        }
        return null;
    }

//from Request

    
    public static void login(String username, String password, HttpServletRequest httpRequest, ServletContext ctx)
    throws ServletException 
    {       
        if (httpRequest.getAuthType() != null || httpRequest.getRemoteUser() != null ||
                httpRequest.getUserPrincipal() != null) {
            throw new ServletException("coyoteRequest.alreadyAuthenticated");
        }
        
        SSPAuthenticator auth = getSSPAuthenticator( ctx);
        if (auth == null) {
            throw new ServletException("no authenticator");
        }
        Request request = getRequest( httpRequest );
        auth.login(username, password, request);
    }

    private static ApplicationContext getContext_ac(ServletContext ctx)
    throws ServletException 
    {
      ApplicationContext context_appctx = null;
      try
      {
        Class<?> c = ApplicationContextFacade.class;
        Field[] fields = c.getDeclaredFields();
        Field field = null;
        for (Field f : fields)
        {
          if ( f.getName().equals("context") )
          {
            field = f;
            break;
          }
        }
        if (field == null) throw new ServletException("NoSuchFieldException");
        else field.setAccessible(true);
         
        ApplicationContextFacade appctx = (ApplicationContextFacade) ctx;
        context_appctx =(ApplicationContext) field.get(appctx);
      }
      catch(IllegalAccessException iae){throw new ServletException("IllegalAccessException");}
      catch(SecurityException se){throw new ServletException("SecurityException");} 
      
      return context_appctx;
    }

    private static StandardContext getContext(ApplicationContext ctx)
    throws ServletException 
    {
      StandardContext context_appctx = null;
      try
      {
        Class<?> c = ApplicationContext.class;
        Field[] fields = c.getDeclaredFields();
        Field field = null;
        for (Field f : fields)
        {
          if ( f.getName().equals("context") )
          {
            field = f;
            break;
          }
        }
        if (field == null) throw new ServletException("NoSuchFieldException");
        else field.setAccessible(true);
         
        context_appctx =(StandardContext) field.get(ctx);
      }
      catch(IllegalAccessException iae){throw new ServletException("IllegalAccessException");}
      catch(SecurityException se){throw new ServletException("SecurityException");} 
      
      return context_appctx;
    }

    private static Request getRequest(HttpServletRequest httpRequest)
    throws ServletException 
    {
      Request request_rf = null;
      try
      {
        Class<?> c = RequestFacade.class;
        Field[] fields = c.getDeclaredFields();
        Field field = null;
        for (Field f : fields)
        {
          if ( f.getName().equals("request") )
          {
            field = f;
            break;
          }
        }
        if (field == null) throw new ServletException("NoSuchFieldException");
        else field.setAccessible(true);
         
        RequestFacade rf = (RequestFacade) httpRequest;
        request_rf =(Request) field.get(rf);
      }
      catch(IllegalAccessException iae){throw new ServletException("IllegalAccessException");}
      catch(SecurityException se){throw new ServletException("SecurityException");} 
 
      return request_rf;
    }

  }
  
  
  
 /* 
   // To add in AUthenticator with tc6
    public void login(String username, String password, Request request)
    throws ServletException {
        Principal principal = doLogin(request, username, password);
        register(request, request.getResponse(), principal,// request.getResponse()? httpServletRequest.getResponse()
                    getAuthMethod(), username, password);  //getAuthMethod()
    }
*/
